#ifndef KERNELSTESTS_H
#define KERNELSTESTS_H

#include <string>
#include <vector>
#include <map>
#include <boost/timer.hpp>
#include <functional>
#include <stdio.h>
#include <conio.h>
#include <fstream>
#include <conio.h>

#include "../../DMMath/src/DMMath.hpp"
#include "../../QueryDataManipulation/src/QueryDataManipulation.hpp"

inline void WriteToLog(std::ofstream& log,const std::string& mess)
{
	if (mess.size())
	{
		log << mess << "\r\n";
	}
}

template<typename Data> void initializeData(std::vector<Data>& data, size_t size)
{
	KDM::math::Random<std::minstd_rand, long int> rnd(0, (long int)size - 1);

	data.resize(size);

	for (size_t i = 0; i < size; i++)
	{
		data[i] = (double)rnd();
	}
};

std::string GetCurrTime()
{
	struct tm *ptr;
	time_t lt;
	char str[80];

	lt = time(NULL);
	ptr = localtime(&lt);
	strftime(str, 80, "%d %m %Y %H:%M:%S", ptr);
	std::string res(str);
	return res;
}


template <typename Data, typename DataIterator> void kernelsSpeedTest(const char* fileName, const std::vector<Data>& data, const std::map<std::string, const QDM::IKernel<DataIterator>*>& kernels, std::function<bool (const DataIterator&)> isRequered, std::function<bool (const DataIterator&, const DataIterator&)> isNeedChange, const char* prefix)
{
	QDM::QueryDataManipulation<DataIterator> query(0);

	std::ofstream log(fileName, std::ios_base::app);
	std::string logMessage;
	std::stringstream buffer;

	logMessage = "************************************************";
	WriteToLog(log, logMessage.c_str());
 
	buffer << "Start " << GetCurrTime() << " " << prefix;
	logMessage = buffer.str();
	WriteToLog(log, logMessage.c_str());

	boost::timer timer;

	for (std::map<std::string, const QDM::IKernel<DataIterator>*>::const_iterator item = kernels.cbegin(); item != kernels.cend(); item++)
	{
		query.setKernel(item->second);
		query.from(data.begin(), data.size());

		buffer.str("");
		buffer << item->first << " SpeedTests start. Data size - " << query.result().size();
		logMessage = buffer.str();
		WriteToLog(log, logMessage.c_str());

		timer.restart();
		query.where(isRequered);

		buffer.str("");
		buffer << item->first << " Where time - " << timer.elapsed() << "; Data size - " << query.result().size();
		logMessage = buffer.str();
		WriteToLog(log, logMessage.c_str());

		timer.restart();
		query.orderBy(isNeedChange);

		buffer.str("");
		buffer << item->first << " OrderBy time - " << timer.elapsed();
		logMessage = buffer.str();
		WriteToLog(log, logMessage.c_str());

		logMessage = "\n";
		WriteToLog(log, logMessage.c_str());
	}

	buffer.str("");
	buffer << "End " << GetCurrTime();
	logMessage = buffer.str();
	WriteToLog(log, logMessage.c_str());

	logMessage = "************************************************";
	WriteToLog(log, logMessage.c_str());
};



#endif